<!-- 个人设置 2025-07-29 14:00徐安修改-->
<template>
  <view class="setting-bg"></view>
  <!-- 返回按鈕 -->
  <view class="setting-container">
        <view class="setting-card">
      <view class="setting-header">
        <view class="setting-title">个人设置</view>
        <button class="logout-btn-small" @click="logout">退出登录</button>
      </view>
      <view class="setting-form">
        <view class="setting-row" v-for="item in userFields" :key="item.key">
          <text class="setting-label">{{ item.label }}：</text>
          <template v-if="item.editable">
            <input
              v-model="editUser[item.key]"
              :type="item.type || 'text'"
              class="setting-input"
              :placeholder="item.label"
              @input="fieldChanged[item.key] = true"
            />
            <button 
              class="setting-btn mini" 
              @click="updateField(item.key)"
              v-if="fieldChanged[item.key]"
            >
              修改
            </button>
          </template>
          <template v-else>
            <view class="setting-value-container">
              <text class="setting-value">{{ user && user[item.key] || '未填写' }}</text>
              <view class="action-buttons" v-if="item.key === 'phone' || item.key === 'email'">
                <button class="action-btn primary" @click="openBindModal(item.key)" v-if="!user || !user[item.key]">绑定</button>
                <button class="action-btn secondary" @click="openRebindModal(item.key)" v-if="user && user[item.key]">换绑</button>
                <button class="action-btn danger" @click="handleUnbind(item.key)" v-if="user && user[item.key]">解绑</button>
              </view>
            </view>
          </template>
        </view>
        <view class="setting-row">
          <text class="setting-label">头像：</text>
          <image :src="user.avatarUrl || defaultAvatar" class="avatar-img" />
          <input type="file" @change="handleAvatarChange" class="avatar-upload" />
        </view>
      </view>
    </view>

    <!-- 偏好设置卡片 -->
    <view class="setting-card prefer-fields-card">
      <view class="setting-title">偏好设置</view>
      <view class="prefer-fields-container">
        <PreferFieldsTree
          :model="rootNode"
          :checkedStatus="checkedStatus"
          :expandedMap="expanded"
          :level="0"
          @check="handleCheckChange"
        />
      </view>
      <button class="setting-btn full-width" @click="savePreferFields">保存偏好设置</button>
    </view>

    <!-- 地区偏好设置卡片 -->
    <view class="setting-card prefer-fields-card">
      <view class="setting-title">地区偏好设置</view>
      <view class="prefer-fields-container">
        <PreferRegionsTree
          :model="regionRootNode"
          :checkedStatus="regionCheckedStatus"
          :expandedMap="regionExpanded"
          :level="0"
          @check="handleRegionCheckChange"
        />
      </view>
      <button class="setting-btn full-width" @click="savePreferRegions">保存地区偏好设置</button>
    </view>

    <!-- 隐私设置卡片 -->
    <view class="setting-card">
      <view class="setting-title">隐私设置</view>
      <view class="privacy-settings-content">
        <view class="privacy-item">
          <view class="privacy-info">
            <view class="privacy-label">🔒 搜索可见性</view>
            <view class="privacy-desc">控制其他用户是否可以通过昵称、手机号等方式搜索到您</view>
          </view>
          <button class="privacy-btn" @click="goToPrivacySettings">
            设置
          </button>
        </view>
      </view>
    </view>

    <!-- 绑定弹窗 -->
    <view class="modal" v-if="bindModalVisible">
      <view class="modal-content">
        <view class="modal-header">
          <text class="modal-title">绑定{{ bindType === 'phone' ? '手机号' : '邮箱' }}</text>
          <text class="close-btn" @click="bindModalVisible = false">&times;</text>
        </view>
        <view class="modal-body">
          <view class="form-group">
            <text class="form-label">{{ bindType === 'phone' ? '手机号' : '邮箱' }}</text>
            <input 
              :type="bindType === 'phone' ? 'tel' : 'email'" 
              v-model="bindForm.identifier" 
              class="setting-input" 
              :placeholder="bindType === 'phone' ? '请输入手机号' : '请输入邮箱'"
            />
          </view>
          <view class="form-group code-group">
            <text class="form-label">验证码</text>
            <input type="text" v-model="bindForm.code" class="setting-input code-input" placeholder="在此输入" />
            <button class="setting-btn mini" @click="sendBindCode" :disabled="bindCountdown > 0">
              {{ bindCountdown > 0 ? `${bindCountdown}秒后重发` : '发送验证码' }}
            </button>
          </view>
          <button class="setting-btn full-width" @click="submitBind">确认绑定</button>
        </view>
      </view>
    </view>

    <!-- 换绑弹窗 -->
    <view class="modal" v-if="rebindModalVisible">
      <view class="modal-content rebind-modal">
        <!-- 弹窗头部：标题和关闭按钮 -->
        <view class="modal-header">
          <text class="modal-title">换绑{{ rebindType === 'phone' ? '手机号' : '邮箱' }}</text>
          <text class="close-btn" @click="rebindModalVisible = false">&times;</text>
        </view>
        
        <view class="modal-body">
          <!-- 页面说明文字 -->
          <text class="form-subtitle">请完成验证，更换您的{{ rebindType === 'phone' ? '手机号' : '邮箱' }}</text>
          
          <!-- 第一步：验证原凭证 -->
          <view class="form-section">
            <!-- 步骤标题：数字图标 + 标题文字 -->
            <view class="section-header">
              <view class="section-icon">1</view>
              <text class="section-title">验证原{{ rebindType === 'phone' ? '手机号' : '邮箱' }}</text>
            </view>
            
            <!-- 原凭证输入框：标签和输入框在同一行 -->
            <view class="form-row">
              <text class="form-label">原{{ rebindType === 'phone' ? '手机号' : '邮箱' }}</text>
              <input :type="rebindType === 'phone' ? 'tel' : 'email'" v-model="rebindForm.oldIdentifier" class="rebind-input disabled" disabled />
            </view>
            
            <!-- 原凭证验证码：标签、输入框、按钮在同一行 -->
            <view class="form-row">
              <text class="form-label">验证码</text>
              <input type="text" v-model="rebindForm.oldCode" class="rebind-input code-input" placeholder="请输入验证码" />
              <button class="code-btn" @click="sendRebindOldCode" :disabled="oldRebindCountdown > 0">
                {{ oldRebindCountdown > 0 ? `${oldRebindCountdown}s` : '发送验证码' }}
              </button>
            </view>
          </view>
          
          <!-- 分隔线：左右线条 + 中间文字 -->
          <view class="divider">
            <view class="divider-line"></view>
            <text class="divider-text">更换为</text>
            <view class="divider-line"></view>
          </view>
          
          <!-- 第二步：设置新凭证 -->
          <view class="form-section">
            <!-- 步骤标题：数字图标 + 标题文字 -->
            <view class="section-header">
              <view class="section-icon">2</view>
              <text class="section-title">设置新{{ rebindType === 'phone' ? '手机号' : '邮箱' }}</text>
            </view>
            
            <!-- 新凭证输入框：标签和输入框在同一行 -->
            <view class="form-row">
              <text class="form-label">新{{ rebindType === 'phone' ? '手机号' : '邮箱' }}</text>
              <input :type="rebindType === 'phone' ? 'tel' : 'email'" v-model="rebindForm.newIdentifier" class="rebind-input" :placeholder="rebindType === 'phone' ? '请输入新手机号' : '请输入新邮箱'" />
            </view>
            
            <!-- 新凭证验证码：标签、输入框、按钮在同一行 -->
            <view class="form-row">
              <text class="form-label">验证码</text>
              <input type="text" v-model="rebindForm.newCode" class="rebind-input code-input" placeholder="请输入验证码" />
              <button class="code-btn" @click="sendRebindNewCode" :disabled="newRebindCountdown > 0 || !rebindForm.newIdentifier">
                {{ newRebindCountdown > 0 ? `${newRebindCountdown}s` : '发送验证码' }}
              </button>
            </view>
          </view>
          
          <!-- 提交按钮 -->
          <button class="rebind-submit-btn" @click="submitRebind">确认换绑</button>
        </view>
      </view>
    </view>
  </view>
  <!-- 退出登录按钮 -->
  
</template>

<script setup>
import { NETWORK_CONFIG } from '@/config/network.js'
import { ref, reactive, onMounted, computed } from 'vue'
import { useUserStore } from '@/store/user'

import { categories } from '@/utils/skillUtils'
import { geoData } from '@/utils/geoUtils'
import PreferFieldsTree from './PreferFieldsTree.vue'
import PreferRegionsTree from './PreferRegionsTree.vue'
import BackButton from '@/components/BackButton.vue'

const userStore = useUserStore()
const user = userStore.getUserInfo
const defaultAvatar = 'https://cdn.jsdelivr.net/gh/seeklogo/ai-assets/avatar-default.png'

const userFields = [
  { key: 'nickname', label: '昵称', editable: true },
  { key: 'signature', label: '个性签名', editable: true },
  { key: 'name', label: '真实姓名', editable: true },
  { key: 'gender', label: '性别', editable: true },
  { key: 'adCode', label: '地区编码', editable: true },
  { key: 'creditCode', label: '协会编码', editable: true },
  { key: 'phone', label: '手机号', editable: false },
  { key: 'email', label: '邮箱', editable: false },
  { key: 'creditScore', label: '信用分', editable: false },
  { key: 'releaseTime', label: '注册时间', editable: false },
]

const editUser = reactive({ ...user })
const fieldChanged = reactive({})

// 绑定相关变量
const bindModalVisible = ref(false)
const bindType = ref('phone') // 'phone' 或 'email'
const bindForm = reactive({
  identifier: '',
  code: ''
})

// 换绑相关变量
const rebindModalVisible = ref(false)
const rebindType = ref('phone') // 'phone' 或 'email'
const rebindForm = reactive({
  oldIdentifier: '',
  oldCode: '',
  newIdentifier: '',
  newCode: ''
})

// 验证码倒计时 - 分别为不同场景设置独立倒计时
const bindCountdown = ref(0)
const oldRebindCountdown = ref(0)
const newRebindCountdown = ref(0)

// 展开状态
const expanded = ref({}) // { '00': true, '0000': false, ... }

// 选中状态
const checked = ref({}) // { '00': true, '0000': false, ... }

// 新增：checkedStatus
const checkedStatus = ref({}) // { '00': 'checked', '0000': 'indeterminate', ... }

const rootNode = {
  code: 'root',
  name: '全部',
  subcategories: categories
}

// 地区偏好相关变量
const regionExpanded = ref({})
const regionCheckedStatus = ref({})

const regionRootNode = {
  adcode: 'root',
  name: '全部',
  cities: geoData
}

// 获取和保存偏好
const fetchPreferFields = async () => {
  const token = uni.getStorageSync('accessToken')
  const res = await uni.request({
    url: `${NETWORK_CONFIG.API_BASE_URL}/user/prefer-fields`,
    method: 'GET',
    header: { 'Access-Token': `Bearer ${token}` }
  })
  if (res.data && Array.isArray(res.data)) {
    initCheckedStatus(res.data)
  }
}
const savePreferFields = async () => {
  const token = uni.getStorageSync('accessToken')
  const codes = collectCheckedCodes()
  await uni.request({
    url: `${NETWORK_CONFIG.API_BASE_URL}/user/change-prefer-fields`,
    method: 'POST',
    data: codes,
    header: { 'Access-Token': `Bearer ${token}` }
  })
  uni.showToast({ 
    title: '保存成功', 
    icon: 'success',
    duration: 2000
  })
}

// 获取和保存地区偏好
const fetchPreferRegions = async () => {
  const token = uni.getStorageSync('accessToken')
  const res = await uni.request({
    url: `${NETWORK_CONFIG.API_BASE_URL}/user/prefer-regions`,
    method: 'GET',
    header: { 'Access-Token': `Bearer ${token}` }
  })
  if (res.data && Array.isArray(res.data)) {
    initRegionCheckedStatus(res.data)
  }
}
const savePreferRegions = async () => {
  const token = uni.getStorageSync('accessToken')
  const codes = collectRegionCheckedCodes()
  await uni.request({
    url: `${NETWORK_CONFIG.API_BASE_URL}/user/change-prefer-regions`,
    method: 'POST',
    data: codes,
    header: { 'Access-Token': `Bearer ${token}` }
  })
  uni.showToast({ 
    title: '保存成功', 
    icon: 'success',
    duration: 2000
  })
}

// 开始倒计时的函数，接收一个ref作为参数
const startCountdown = (countdownRef) => {
  countdownRef.value = 60
  const timer = setInterval(() => {
    countdownRef.value--
    if (countdownRef.value <= 0) {
      clearInterval(timer)
    }
  }, 1000)
}

// 获取用户信息
const fetchUser = async () => {
  try {
    const token = uni.getStorageSync('accessToken')
    const res = await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user/me`,
      method: 'POST',
      header: { 'Access-Token': `Bearer ${token}` }
    })
    userStore.setUser(res.data)
    Object.assign(editUser, res.data)
    // 重置修改标记
    Object.keys(fieldChanged).forEach(key => {
      fieldChanged[key] = false
    })
  } catch (error) {
    uni.showToast({
      title: '获取用户信息失败',
      icon: 'none'
    })
    console.error('获取用户信息失败:', error)
  }
}

// 更新单个字段
const updateField = async (key) => {
  try {
    const token = uni.getStorageSync('accessToken')
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user/update`,
      method: 'POST',
      data: {
        [key]: editUser[key]
      },
      header: { 'Access-Token': `Bearer ${token}` }
    })
    await fetchUser()
    uni.showToast(`${userFields.find(f => f.key === key).label}修改成功`)
    fieldChanged[key] = false
    
    // 发送用户信息更新事件
    uni.$emit('user-profile-updated', { field: key, value: editUser[key] })
  } catch (error) {
    uni.showToast({
      title: '修改失败',
      icon: 'none'
    })
    console.error('修改失败:', error)
  }
}

// 打开绑定模态框
const openBindModal = (type) => {
  bindType.value = type
  bindForm.identifier = ''
  bindForm.code = ''
  bindCountdown.value = 0 // 重置倒计时
  bindModalVisible.value = true
}

// 打开换绑模态框
const openRebindModal = (type) => {
  rebindType.value = type
  rebindForm.oldIdentifier = type === 'phone' ? user.phone : user.email
  rebindForm.oldCode = ''
  rebindForm.newIdentifier = ''
  rebindForm.newCode = ''
  oldRebindCountdown.value = 0 // 重置旧凭证倒计时
  newRebindCountdown.value = 0 // 重置新凭证倒计时
  rebindModalVisible.value = true
}

// 发送绑定验证码
const sendBindCode = async () => {
  try {
    if (!bindForm.identifier) {
      uni.showToast({
        title: `请输入${bindType.value === 'phone' ? '手机号' : '邮箱'}`,
        icon: 'none'
      })
      return
    }

    const isPhone = bindType.value === 'phone'
    
    // 验证格式
    if (isPhone && !/^1[3-9]\d{9}$/.test(bindForm.identifier)) {
      uni.showToast({
        title: '手机号格式不正确',
        icon: 'none'
      })
      return
    }
    
    if (!isPhone && !/^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}$/.test(bindForm.identifier)) {
      uni.showToast({
        title: '邮箱格式不正确',
        icon: 'none'
      })
      return
    }

    const endpoint = isPhone ? '/bind/send-phone-code' : '/bind/send-email-code'
    
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user${endpoint}`,
      method: 'POST',
      data: {
        identifier: bindForm.identifier
      }
    })
    
    uni.showToast({
      title: '验证码已发送',
      icon: 'success'
    })
    startCountdown(bindCountdown) // 使用绑定场景的倒计时
  } catch (error) {
    uni.showToast({
      title: error.response?.data?.message || '发送验证码失败',
      icon: 'none'
    })
    console.error('发送验证码失败:', error)
  }
}

// 提交绑定
const submitBind = async () => {
  try {
    if (!bindForm.identifier || !bindForm.code) {
      uni.showToast({
        title: `${bindType.value === 'phone' ? '手机号' : '邮箱'}和验证码不能为空`,
        icon: 'none'
      })
      return
    }

    const isPhone = bindType.value === 'phone'
    const endpoint = isPhone ? '/bind/phone' : '/bind/email'
    const key = isPhone ? 'phone' : 'email'
    
    const token = uni.getStorageSync('accessToken')
    
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user${endpoint}`,
      method: 'POST',
      data: {
        [key]: bindForm.identifier,
        code: bindForm.code
      },
      header: { 'Access-Token': `Bearer ${token}` }
    })
    
    uni.showToast({
      title: `${isPhone ? '手机号' : '邮箱'}绑定成功`,
      icon: 'success'
    })
    bindModalVisible.value = false
    await fetchUser()
  } catch (error) {
    uni.showToast({
      title: error.response?.data?.message || '绑定失败',
      icon: 'none'
    })
    console.error('绑定失败:', error)
  }
}

// 发送原凭证验证码
const sendRebindOldCode = async () => {
  try {
    const isPhone = rebindType.value === 'phone'
    const endpoint = isPhone ? '/rebind/send-phone-code' : '/rebind/send-email-code'
    
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user${endpoint}`,
      method: 'POST',
      data: {
        identifier: rebindForm.oldIdentifier
      }
    })
    
    uni.showToast({
      title: '验证码已发送',
      icon: 'success'
    })
    startCountdown(oldRebindCountdown) // 使用旧凭证的倒计时
  } catch (error) {
    uni.showToast({
      title: error.response?.data?.message || '发送验证码失败',
      icon: 'none'
    })
    console.error('发送验证码失败:', error)
  }
}

// 发送新凭证验证码
const sendRebindNewCode = async () => {
  try {
    if (!rebindForm.newIdentifier) {
      uni.showToast({
        title: `请输入新${rebindType.value === 'phone' ? '手机号' : '邮箱'}`,
        icon: 'none'
      })
      return
    }

    const isPhone = rebindType.value === 'phone'
    
    // 验证格式
    if (isPhone && !/^1[3-9]\d{9}$/.test(rebindForm.newIdentifier)) {
      uni.showToast({
        title: '手机号格式不正确',
        icon: 'none'
      })
      return
    }
    
    if (!isPhone && !/^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}$/.test(rebindForm.newIdentifier)) {
      uni.showToast({
        title: '邮箱格式不正确',
        icon: 'none'
      })
      return
    }

    const endpoint = isPhone ? '/bind/send-phone-code' : '/bind/send-email-code'
    
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user${endpoint}`,
      method: 'POST',
      data: {
        identifier: rebindForm.newIdentifier
      }
    })
    
    uni.showToast({
      title: '验证码已发送',
      icon: 'success'
    })
    startCountdown(newRebindCountdown) // 使用新凭证的倒计时
  } catch (error) {
    uni.showToast({
      title: error.response?.data?.message || '发送验证码失败',
      icon: 'none'
    })
    console.error('发送验证码失败:', error)
  }
}

// 提交换绑
const submitRebind = async () => {
  try {
    if (!rebindForm.oldCode || !rebindForm.newIdentifier || !rebindForm.newCode) {
      uni.showToast({
        title: '请填写完整信息',
        icon: 'none'
      })
      return
    }

    const isPhone = rebindType.value === 'phone'
    const endpoint = isPhone ? '/rebind/phone' : '/rebind/email'
    const oldKey = isPhone ? 'oldPhone' : 'oldEmail'
    const newKey = isPhone ? 'newPhone' : 'newEmail'
    
    const token = uni.getStorageSync('accessToken')
    
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user${endpoint}`,
      method: 'POST',
      data: {
        [oldKey]: rebindForm.oldIdentifier,
        'oldCode': rebindForm.oldCode,
        [newKey]: rebindForm.newIdentifier,
        'newCode': rebindForm.newCode
      },
      header: { 'Access-Token': `Bearer ${token}` }
    })
    
    uni.showToast({
      title: `${isPhone ? '手机号' : '邮箱'}换绑成功`,
      icon: 'success'
    })
    rebindModalVisible.value = false
    await fetchUser()
  } catch (error) {
    uni.showToast({
      title: error.response?.data?.message || '换绑失败',
      icon: 'none'
    })
    console.error('换绑失败:', error)
  }
}

// 解绑
const handleUnbind = async (key) => {
  try {
    // #ifdef H5
    if (!confirm(`确定要解绑${key === 'phone' ? '手机号' : '邮箱'}吗？`)) return
    // #endif
    // #ifdef MP-WEIXIN
    const [error, res] = await uni.showModal({
      title: '确认解绑',
      content: `确定要解绑${key === 'phone' ? '手机号' : '邮箱'}吗？`,
      confirmText: '确定',
      cancelText: '取消'
    });
    if (error || !res.confirm) return;
    // #endif
    
    const token = uni.getStorageSync('accessToken')
    await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user/unbind/${key}`,
      method: 'POST',
      header: { 'Access-Token': `Bearer ${token}` }
    })
    await fetchUser()
    uni.showToast({
      title: '解绑成功',
      icon: 'success'
    })
  } catch (error) {
    uni.showToast({
      title: '解绑失败',
      icon: 'none'
    })
    console.error('解绑失败:', error)
  }
}

// 头像上传
const handleAvatarChange = async (e) => {
  try {
    const file = e.target.files[0]
    if (!file) return
    
    // 显示上传中的提示
    uni.showToast({
      title: '头像上传中...',
      icon: 'loading'
    })
    
    // 创建FormData对象
    const formData = new FormData()
    formData.append('file', file)
    
    const token = uni.getStorageSync('accessToken')
    const res = await uni.request({
      url: `${NETWORK_CONFIG.API_BASE_URL}/user/avatar`,
      method: 'POST',
      data: formData,
      header: { 
        'Access-Token': `Bearer ${token}`,
        'Content-Type': 'multipart/form-data'
      }
    })
    
    // 更新头像链接并刷新用户信息
    if (res.data && res.data.url) {
      await updateField('avatarUrl')
      uni.showToast({
        title: '头像上传成功',
        icon: 'success'
      })
    }
  } catch (error) {
    uni.showToast({
      title: '头像上传失败',
      icon: 'none'
    })
    console.error('头像上传失败:', error)
  }
}

// 勾选/取消时递归处理
const handleCheckChange = (node, level, checked) => {
  // 1. 设置本节点及所有子节点
  setNodeAndChildrenStatus(node, checked ? 'checked' : '')
  // 2. 向上递归更新父节点
  updateParentStatus(node)
}

// 递归设置本节点及所有子节点状态
function setNodeAndChildrenStatus(node, status) {
  checkedStatus.value[node.code] = status
  const children = node.subcategories || node.directions
  if (children) {
    children.forEach(child => setNodeAndChildrenStatus(child, status))
  }
}

// 递归向上更新父节点状态
function updateParentStatus(node) {
  // 找父节点
  let parent = null
  let parentList = []
  function findParent(nodes) {
    for (const n of nodes) {
      const children = n.subcategories || n.directions
      if (children && children.some(child => child.code === node.code)) {
        parent = n
        parentList = children
        return
      }
      if (children) findParent(children)
    }
  }
  findParent(categories)
  if (parent) {
    // 统计所有子节点状态
    const allChecked = parentList.every(child => checkedStatus.value[child.code] === 'checked')
    const someChecked = parentList.some(child => checkedStatus.value[child.code] === 'checked' || checkedStatus.value[child.code] === 'indeterminate')
    if (allChecked) {
      checkedStatus.value[parent.code] = 'checked'
    } else if (someChecked) {
      checkedStatus.value[parent.code] = 'indeterminate'
    } else {
      checkedStatus.value[parent.code] = ''
    }
    // 递归向上
    updateParentStatus(parent)
  }
  // 额外：如果当前节点是 1 级节点，更新 0 级节点状态
  if (node.code.length === 2) {
    const allFirstLevelChecked = categories.every(child => checkedStatus.value[child.code] === 'checked')
    const someFirstLevelChecked = categories.some(child => checkedStatus.value[child.code] === 'checked' || checkedStatus.value[child.code] === 'indeterminate')
    if (allFirstLevelChecked) {
      checkedStatus.value['root'] = 'checked'
    } else if (someFirstLevelChecked) {
      checkedStatus.value['root'] = 'indeterminate'
    } else {
      checkedStatus.value['root'] = ''
    }
  }
}

// 初始化选中和展开（根据后端返回的数组）
const initCheckedFromBackend = (arr) => {
  checked.value = {}
  expanded.value = {}
  arr.forEach(code => {
    checked.value[code] = true
    // 展开所有父节点
    if (code.length >= 2) expanded.value[code.slice(0, 2)] = true
    if (code.length >= 4) expanded.value[code.slice(0, 4)] = true
  })
}

// 递归收集所有选中的节点，去冗余（只保留最顶层被选中的code）
const collectCheckedCodes = () => {
  // 判断全选
  if (checkedStatus.value['root'] === 'checked') return []
  // 判断全不选
  if (checkedStatus.value['root'] === '') return ['-']
  // 部分选中，递归收集
  const result = []
  function walk(nodes) {
    nodes.forEach(node => {
      const code = node.code
      if (checkedStatus.value[code] === 'checked') {
        result.push(code)
      } else if (checkedStatus.value[code] === 'indeterminate') {
        const children = node.subcategories || node.directions
        if (children) walk(children)
      }
    })
  }
  walk(categories)
  return result
}

function initCheckedStatus(codes) {
  checkedStatus.value = {}
  // 全选
  if (!codes || codes.length === 0) {
    setAllChildrenChecked(rootNode)
    checkedStatus.value['root'] = 'checked'
    return
  }
  // 全不选
  if (codes.length === 1 && codes[0] === '-') {
    clearAllChildren(rootNode)
    checkedStatus.value['root'] = ''
    return
  }
  // 其它情况递归
  function setAllChildrenChecked(node) {
    checkedStatus.value[node.code] = 'checked'
    const children = node.subcategories || node.directions
    if (children) children.forEach(setAllChildrenChecked)
  }
  function clearAllChildren(node) {
    checkedStatus.value[node.code] = ''
    const children = node.subcategories || node.directions
    if (children) children.forEach(clearAllChildren)
  }
  // 递归设置
  function walk(node) {
    const code = node.code
    if (codes.includes(code)) {
      checkedStatus.value[code] = 'checked'
      const children = node.subcategories || node.directions
      if (children) children.forEach(setAllChildrenChecked)
    } else {
      const children = node.subcategories || node.directions
      if (children && children.length) {
        children.forEach(walk)
        const allChecked = children.every(child => checkedStatus.value[child.code] === 'checked')
        const someChecked = children.some(child => checkedStatus.value[child.code] && checkedStatus.value[child.code] !== '')
        if (allChecked) {
          checkedStatus.value[code] = 'checked'
        } else if (someChecked) {
          checkedStatus.value[code] = 'indeterminate'
        } else {
          checkedStatus.value[code] = ''
        }
      } else {
        checkedStatus.value[code] = codes.includes(code) ? 'checked' : ''
      }
    }
  }
  walk(rootNode)
}

// 地区偏好相关方法
const handleRegionCheckChange = (node, level, checked) => {
  setNodeAndChildrenRegionStatus(node, checked ? 'checked' : '')
  updateRegionParentStatus(node)
}

function setNodeAndChildrenRegionStatus(node, status) {
  regionCheckedStatus.value[node.adcode] = status
  const children = node.cities || node.districts
  if (children) {
    children.forEach(child => setNodeAndChildrenRegionStatus(child, status))
  }
}

function updateRegionParentStatus(node) {
  let parent = null
  let parentList = []
  function findParent(nodes) {
    for (const n of nodes) {
      const children = n.cities || n.districts
      if (children && children.some(child => child.adcode === node.adcode)) {
        parent = n
        parentList = children
        return
      }
      if (children) findParent(children)
    }
  }
  findParent(geoData)
  if (parent) {
    const allChecked = parentList.every(child => regionCheckedStatus.value[child.adcode] === 'checked')
    const someChecked = parentList.some(child => regionCheckedStatus.value[child.adcode] === 'checked' || regionCheckedStatus.value[child.adcode] === 'indeterminate')
    if (allChecked) {
      regionCheckedStatus.value[parent.adcode] = 'checked'
    } else if (someChecked) {
      regionCheckedStatus.value[parent.adcode] = 'indeterminate'
    } else {
      regionCheckedStatus.value[parent.adcode] = ''
    }
    updateRegionParentStatus(parent)
  }
  // 只要是省级节点，更新根节点三态
  if (node.adcode.length === 2) {
    const allFirstLevelChecked = geoData.every(child => regionCheckedStatus.value[child.adcode] === 'checked')
    const someFirstLevelChecked = geoData.some(child => regionCheckedStatus.value[child.adcode] === 'checked' || regionCheckedStatus.value[child.adcode] === 'indeterminate')
    if (allFirstLevelChecked) {
      regionCheckedStatus.value['root'] = 'checked'
    } else if (someFirstLevelChecked) {
      regionCheckedStatus.value['root'] = 'indeterminate'
    } else {
      regionCheckedStatus.value['root'] = ''
    }
  }
}

// 收集所有选中的地区code
const collectRegionCheckedCodes = () => {
  if (regionCheckedStatus.value['root'] === 'checked') return []
  if (regionCheckedStatus.value['root'] === '') return ['-']
  const result = []
  function walk(nodes) {
    nodes.forEach(node => {
      const adcode = node.adcode
      if (regionCheckedStatus.value[adcode] === 'checked') {
        result.push(adcode)
      } else if (regionCheckedStatus.value[adcode] === 'indeterminate') {
        const children = node.cities || node.districts
        if (children) walk(children)
      }
    })
  }
  walk(geoData)
  return result
}

// 初始化选中状态
function initRegionCheckedStatus(codes) {
  regionCheckedStatus.value = {}
  if (!codes || codes.length === 0) {
    setAllChildrenRegionChecked(regionRootNode)
    regionCheckedStatus.value['root'] = 'checked'
    return
  }
  if (codes.length === 1 && codes[0] === '-') {
    clearAllChildrenRegion(regionRootNode)
    regionCheckedStatus.value['root'] = ''
    return
  }
  function setAllChildrenRegionChecked(node) {
    regionCheckedStatus.value[node.adcode] = 'checked'
    const children = node.cities || node.districts
    if (children) children.forEach(setAllChildrenRegionChecked)
  }
  function clearAllChildrenRegion(node) {
    regionCheckedStatus.value[node.adcode] = ''
    const children = node.cities || node.districts
    if (children) children.forEach(clearAllChildrenRegion)
  }
  function walk(node) {
    const adcode = node.adcode
    if (codes.includes(adcode)) {
      regionCheckedStatus.value[adcode] = 'checked'
      const children = node.cities || node.districts
      if (children) children.forEach(setAllChildrenRegionChecked)
    } else {
      const children = node.cities || node.districts
      if (children && children.length) {
        children.forEach(walk)
        const allChecked = children.every(child => regionCheckedStatus.value[child.adcode] === 'checked')
        const someChecked = children.some(child => regionCheckedStatus.value[child.adcode] && regionCheckedStatus.value[child.adcode] !== '')
        if (allChecked) {
          regionCheckedStatus.value[adcode] = 'checked'
        } else if (someChecked) {
          regionCheckedStatus.value[adcode] = 'indeterminate'
        } else {
          regionCheckedStatus.value[adcode] = ''
        }
      } else {
        regionCheckedStatus.value[adcode] = codes.includes(adcode) ? 'checked' : ''
      }
    }
  }
  walk(regionRootNode)
}

const logout = () => {
  uni.removeStorageSync('accessToken');
  uni.reLaunch({
    url: '/pages/auth/login/index',
    fail: (err) => {
      console.error('跳转到登录页面失败:', err);
      uni.showToast({
        title: '页面跳转失败',
        icon: 'none'
      });
    }
  });
};

// 跳转到隐私设置页面
const goToPrivacySettings = () => {
  uni.navigateTo({
    url: '/pages/setting/privacy'
  });
};

onMounted(() => {
  fetchUser()
  fetchPreferFields()
  fetchPreferRegions()
})
</script>

<style scoped>
.setting-bg {
  position: fixed;
  z-index: 0;
  left: 0; top: 0; width: 100vw; height: 100vh;
  background: #4a90e2;
  overflow: hidden;
}

.setting-container {
  position: relative;
  z-index: 1;
  padding: 32px 0;
  max-width: 600px;
  margin: 0 auto;
  font-family: Arial, sans-serif;
}

.setting-card {
  background: #fff;
  border-radius: 24px;
  padding: 32px 40px;
  border: 2px solid #e0c3fc;
}

.setting-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 22px;
}

.setting-title {
  color: #4a90e2;
  font-size: 2.1rem;
  font-weight: bold;
  letter-spacing: 2px;
  margin: 0;
}

.setting-form {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.setting-row {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  padding-bottom: 12px;
  border-bottom: 1px solid #e0c3fc;
  flex-wrap: wrap;
}

.setting-value-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.action-buttons {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.setting-label {
  color: #4a90e2;
  font-weight: bold;
  min-width: 100px;
  font-size: 1.18rem;
}

.setting-input {
  background: #f3e9ff;
  color: #4a90e2;
  border: 1.5px solid #4a90e2;
  border-radius: 10px;
  padding: 8px 20px;
  font-size: 1.08rem;
  font-weight: bold;
  outline: none;
  min-width: 180px;
  font-family: inherit;
}

.setting-value {
  color: #666;
  font-size: 1.08rem;
  min-width: 180px;
}

.setting-btn {
  background: #a1c4fd;
  color: #4a90e2;
  border: none;
  border-radius: 10px;
  padding: 7px 22px;
  font-size: 1.08rem;
  font-weight: bold;
  font-family: inherit;
}

.setting-btn:disabled {
  opacity: 0.6;
}

.setting-btn.ghost {
  background: transparent;
  color: #a259ff;
  border: 1.5px solid #a259ff;
}

.setting-btn.mini {
  padding: 5px 14px;
  font-size: 0.98rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.action-btn {
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 500;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
  min-width: 50px;
  text-align: center;
}

.action-btn.primary {
  background: #4a90e2;
  color: white;
}

.action-btn.primary:active {
  background: #3a7bc8;
  transform: scale(0.95);
}

.action-btn.secondary {
  background: #f0f8ff;
  color: #4a90e2;
  border: 1px solid #4a90e2;
}

.action-btn.secondary:active {
  background: #e0f0ff;
  transform: scale(0.95);
}

.action-btn.danger {
  background: #fff5f5;
  color: #e53e3e;
  border: 1px solid #e53e3e;
}

.action-btn.danger:active {
  background: #fed7d7;
  transform: scale(0.95);
}

.setting-btn.full-width {
  width: 100%;
  margin-top: 15px;
}

.avatar-img {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid #4a90e2;
  flex-shrink: 0;
}

.avatar-upload {
  margin-left: 10px;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #0008;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-content {
  background: #fff;
  border-radius: 20px;
  padding: 25px;
  width: 90%;
  max-width: 450px;
  border: 2px solid #e0c3fc;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  border-bottom: 2px solid #e0c3fc;
  padding-bottom: 10px;
}

.modal-header h3 {
  color: #a259ff;
  font-size: 1.5rem;
  margin: 0;
}

.modal-title {
  color: #a259ff;
  font-size: 1.5rem;
  margin: 0;
}

.close-btn {
  font-size: 24px;
  color: #a259ff;
}

.modal-body {
  padding: 10px 0;
}

.form-group {
  margin-bottom: 15px;
}

.form-title {
  color: #a259ff;
  font-size: 1.2rem;
  margin-bottom: 15px;
  text-align: center;
}

.form-group label {
  display: block;
  color: #a259ff;
  margin-bottom: 5px;
  font-size: 1.05rem;
}

.form-label {
  display: block;
  color: #a259ff;
  margin-bottom: 5px;
  font-size: 1.05rem;
}

.code-group {
  display: flex;
  gap: 10px;
}

.code-input {
  width: 120px;
}

.divider {
  text-align: center;
  margin: 20px 0;
}

.divider span {
  background: #fff;
  padding: 5px 10px;
  border-radius: 10px;
  font-size: 1.05rem;
  color: #a259ff;
  font-weight: bold;
}

/* 换绑弹窗优化样式 */
.rebind-modal {
  max-width: 500px; /* 弹窗最大宽度 */
  width: 90%; /* 弹窗宽度占屏幕90% */
}

.form-subtitle {
  color: #666; /* 副标题颜色 */
  font-size: 1rem; /* 字体大小 */
  margin-bottom: 20px; /* 底部间距 */
  text-align: center; /* 居中对齐 */
  line-height: 1.5; /* 行高 */
}

.form-section {
  margin-bottom: 24px; /* 底部间距 */
  padding: 16px; /* 内边距 */
  background: #f8f9ff; /* 浅蓝色背景 */
  border-radius: 12px; /* 圆角 */
  border: 1px solid #e0e7ff; /* 边框 */
}

.section-header {
  display: flex; /* 弹性布局 */
  align-items: center; /* 垂直居中 */
  margin-bottom: 16px; /* 底部间距 */
  gap: 12px; /* 元素间距 */
}

.section-icon {
  width: 24px; /* 图标宽度 */
  height: 24px; /* 图标高度 */
  background: #4a90e2; /* 蓝色背景 */
  color: white; /* 白色文字 */
  border-radius: 50%; /* 圆形 */
  display: flex; /* 弹性布局 */
  align-items: center; /* 垂直居中 */
  justify-content: center; /* 水平居中 */
  font-size: 0.9rem; /* 字体大小 */
  font-weight: bold; /* 粗体 */
}

.section-title {
  color: #4a90e2; /* 蓝色文字 */
  font-size: 1.1rem; /* 字体大小 */
  font-weight: bold; /* 粗体 */
}

/* 表单行布局：标签、输入框、按钮在同一行 */
.form-row {
  display: flex; /* 弹性布局 */
  align-items: center; /* 垂直居中 */
  gap: 12px; /* 元素间距 */
  margin-bottom: 12px; /* 底部间距 */
}

.form-row:last-child {
  margin-bottom: 0; /* 最后一行不需要底部间距 */
}

.form-label {
  min-width: 80px; /* 标签最小宽度，保持对齐 */
  color: #4a90e2; /* 蓝色文字 */
  font-size: 0.9rem; /* 字体大小 */
  font-weight: 500; /* 字体粗细 */
}

.rebind-input {
  flex: 1; /* 输入框占据剩余空间 */
  background: #fff; /* 白色背景 */
  color: #333; /* 深灰色文字 */
  border: 1.5px solid #e0e7ff; /* 边框 */
  border-radius: 8px; /* 圆角 */
  padding: 12px 16px; /* 内边距 */
  font-size: 1rem; /* 字体大小 */
  outline: none; /* 移除默认轮廓 */
  font-family: inherit; /* 继承字体 */
  transition: border-color 0.2s ease; /* 边框颜色过渡动画 */
}

.rebind-input:focus {
  border-color: #4a90e2; /* 聚焦时边框变蓝 */
}

.rebind-input.disabled {
  background: #f5f5f5; /* 禁用状态背景色 */
  color: #999; /* 禁用状态文字颜色 */
  cursor: not-allowed; /* 禁用状态光标 */
}

.rebind-input.code-input {
  flex: 1; /* 验证码输入框占据剩余空间 */
  margin-right: 8px; /* 右侧间距，与按钮分开 */
}

.code-btn {
  background: #4a90e2; /* 蓝色背景 */
  color: white; /* 白色文字 */
  border: none; /* 无边框 */
  border-radius: 6px; /* 圆角 */
  padding: 12px 16px; /* 内边距 */
  font-size: 0.9rem; /* 字体大小 */
  font-weight: 500; /* 字体粗细 */
  cursor: pointer; /* 手型光标 */
  transition: all 0.2s ease; /* 过渡动画 */
  white-space: nowrap; /* 文字不换行 */
  min-width: 80px; /* 最小宽度 */
  flex-shrink: 0; /* 不收缩 */
}

.code-btn:disabled {
  background: #ccc; /* 禁用状态背景色 */
  cursor: not-allowed; /* 禁用状态光标 */
}

.code-btn:not(:disabled):active {
  background: #3a7bc8; /* 点击时背景色变深 */
  transform: scale(0.95); /* 点击时缩小 */
}

.divider {
  display: flex; /* 弹性布局 */
  align-items: center; /* 垂直居中 */
  margin: 24px 0; /* 上下间距 */
  gap: 12px; /* 元素间距 */
}

.divider-line {
  flex: 1; /* 线条占据剩余空间 */
  height: 1px; /* 线条高度 */
  background: #e0e7ff; /* 线条颜色 */
}

.divider-text {
  color: #4a90e2; /* 文字颜色 */
  font-size: 0.9rem; /* 字体大小 */
  font-weight: 500; /* 字体粗细 */
  padding: 0 12px; /* 左右内边距 */
}

.rebind-submit-btn {
  background: linear-gradient(135deg, #4a90e2 0%, #357abd 100%); /* 渐变背景 */
  color: white; /* 白色文字 */
  border: none; /* 无边框 */
  border-radius: 12px; /* 圆角 */
  padding: 16px 24px; /* 内边距 */
  font-size: 1.1rem; /* 字体大小 */
  font-weight: bold; /* 粗体 */
  cursor: pointer; /* 手型光标 */
  transition: all 0.2s ease; /* 过渡动画 */
  width: 100%; /* 全宽 */
  margin-top: 16px; /* 顶部间距 */
  box-shadow: 0 4px 12px rgba(74, 144, 226, 0.3); /* 阴影 */
}

.rebind-submit-btn:active {
  transform: translateY(1px); /* 点击时向下移动 */
  box-shadow: 0 2px 8px rgba(74, 144, 226, 0.4); /* 点击时阴影变化 */
}

.prefer-fields-card {
  margin-top: 24px;
}

.prefer-fields-container {
  max-height: 500px;
  overflow-y: auto;
  padding: 10px;
}

.setting-logout-row {
  margin-top: 32px;
  display: flex;
  justify-content: center;
}
.logout-btn-small {
  background: #5a90e2;
  color: #fff;
  font-weight: bold;
  border: none;
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 0.9rem;
  min-width: 60px;
}

.logout-btn {
  background: #ff5858;
  color: #fff;
  font-weight: bold;
  border: none;
  border-radius: 12px;
  padding: 12px 0;
  font-size: 1.15rem;
}

/* 隐私设置样式 */
.privacy-settings-content {
  padding: 16px 0;
}

.privacy-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 0;
  border-bottom: 1px solid #f0f0f0;
}

.privacy-item:last-child {
  border-bottom: none;
}

.privacy-info {
  flex: 1;
  margin-right: 16px;
}

.privacy-label {
  font-size: 16px;
  font-weight: 500;
  color: #333;
  margin-bottom: 4px;
}

.privacy-desc {
  font-size: 12px;
  color: #999;
  line-height: 1.4;
}

.privacy-btn {
  background: #4a90e2;
  color: white;
  border: none;
  border-radius: 8px;
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
}

.privacy-btn:hover {
  background: #3a7bc8;
  transform: scale(1.05);
}
</style>
